package com.glory.hikvisionmobile.customView;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * *****************************
 *
 * @Anthor yazhou
 * @Email 1184545990@qq.com
 * @Time 2020/3/31 18:19
 * @DESC *****************************
 */
public class HikZoomView extends FrameLayout implements GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener, GestureDetector.OnDoubleTapListener {

    private static final String TAG = "HikZoomView";


    private HikGestureDetector mHikGestureDetector;

    private Paint mPaint;
    private Matrix matrix;

    private long downTime;


    public HikZoomView(@NonNull Context context) {
        super(context);
        _init(context, null,0,0);
    }

    public HikZoomView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        _init(context, attrs, 0,0);
    }

    public HikZoomView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        _init(context, attrs, defStyleAttr, 0);
    }

    public HikZoomView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        _init(context, attrs, defStyleAttr, defStyleRes);
    }

    private void _init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        mHikGestureDetector = new HikGestureDetector(context, this, this);
        mHikGestureDetector.setOnDoubleTapListener(this);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        matrix = new Matrix();
        matrix.setScale(1,1);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        float scale = logMatrix()[4];
        if (scale == 1 && ev.getPointerCount() == 1) {
            return super.dispatchTouchEvent(ev);
        } else {
            mHikGestureDetector.onTouchEvent(ev);

            float[] values = logMatrix();
            float x = ev.getX();
            float y = ev.getY();
            float pX = x - values[2];
            float pY = y - values[5];
            ev.setLocation(pX / values[4], pY / values[4]);
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downTime = System.currentTimeMillis();
                    super.dispatchTouchEvent(ev);
                    break;
                case MotionEvent.ACTION_MOVE:
//                    downTime = 0;
                    break;
                case MotionEvent.ACTION_UP:
                    long spanTime = System.currentTimeMillis() - downTime;
                    if (spanTime < 500l) {
                        super.dispatchTouchEvent(ev);
//                        Log.i(TAG, "onSingleTapConfirmed " + ev.toString());
                    }
                    break;
            }
            return true;
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (getChildCount() > 0) {
//            getChildAt(0).setDrawingCacheEnabled(true);
//            Bitmap bitmap = getChildAt(0).getDrawingCache();
            if (logMatrix()[4] > 1) {
                canvas.concat(matrix);
                getChildAt(0).draw(canvas);
//                canvas.drawBitmap(bitmap, matrix, mPaint);
            }
        }
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
//        Log.i(TAG, "onSingleTapUp");
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        float[] values = logMatrix();
        float s = values[4];
        float offX = Math.max(getWidth() - getWidth() * s, Math.min(0, values[2] - distanceX));
        float offY = Math.max(getHeight() - getHeight() * s, Math.min(0, values[5] - distanceY));;

        matrix.postTranslate(offX - values[2], offY - values[5]);

        invalidate();
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scale = detector.getScaleFactor();

        float cunS = logMatrix()[4];
        if (cunS * scale < 1f) {
            scale = 1f / cunS;
        } else if (cunS * scale > 2f) {
            scale = 2f / cunS;
        }
        matrix.postScale(scale, scale);
        invalidate();
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {

    }

    private float[] logMatrix() {
        float[] values = new float[9];
        matrix.getValues(values);
//        for (int i = 0; i < values.length; i++) {
//            Log.i(TAG, "value " + i + " = " + values[i]);
//        }
        return values;
    }
}
